Overview
Details on the construction of the MedStar EPCR Patient symptom table. 126 unique symptoms were recorded for 2853 calls. A total of 4086 symptoms were recorded among the calls.
Load packages and data
library(tidyverse)
library(bfuncs)
symptoms <- feather::read_feather("/Users/jaredwiegand/Desktop/DETECT Repository/symptoms.feather")
- Adding file path for DETECT data server.
- Brad emailed Chris Harvey on 2019-02-11 to make Jared an authorized user.
symptoms <- feather::read_feather("/Volumes/DETECT/one_year_data/symptoms.feather")
about_data(symptoms) # 28,228 observations and 2 variables
[1] "28,228 observations and 2 variables"
top
Simplify symptom list
Currently, the symptom list includes upper and lower case letters, spaces, and special characters. These are not characteristics we want on our variable names, and they make matching with regular expressions more difficult. We want to do both of those things below. So, here we will:
- Convert all letters to lower case
- Replace spaces with underscores
- Replace parentheses with underscores
- Replace periods with underscores
- Replace commas with underscores
- Replace all instances of 2 or more consecutive underscores we created in the process with single underscores
- Remove trailing underscores
simplify_symptom_strings <- function(x) {
x %>%
tolower() %>%
stringr::str_replace_all(pattern = "\\s", replacement = "_") %>% # white space
stringr::str_replace_all(pattern = "[\\(|\\)]", replacement = "_") %>% # parentheses
stringr::str_replace_all(pattern = "\\.", replacement = "_") %>% # periods
stringr::str_replace_all(pattern = "\\,(?=\\_)", replacement = "_") %>% # commas - not separating symptoms
stringr::str_replace_all(pattern = "\\_{2,}", replacement = "_") %>% # multiple underscores
stringr::str_replace_all(pattern = "\\_(?=\\')", replacement = "") # trailing underscores
}
symptoms <- symptoms %>%
mutate(symptoms_simplified = simplify_symptom_strings(symptoms))
about_data(symptoms) # 28,228 observations and 3 variables
[1] "28,228 observations and 3 variables"
top
Find all symptoms
- Figure out how to break character stings into component symptoms
- Get list of all unique symptoms
- Turn symptoms into binary variables
- Create new table of symptoms
- Create two-way table of symptoms by incident complaint
Create List of Unique Symptoms
symptom_list <- symptoms %>%
filter(!is.na(symptoms_simplified)) %>% # Remove NA
pull(symptoms_simplified) %>% # Coerce to vector
unique() %>% # Gets unique groups of symptoms
stringr::str_split(pattern = "'',''") %>% # Splits character string at '',''
unlist() %>% # Coerce from list to vector
stringr::str_remove_all("'") %>% # Remove remaining single quotes
unique() # Get unique symptoms
Create dummy variables for each symptom, by the same name
for (i in seq_along(symptom_list)) {
symptoms[symptom_list[i]] <- NA
}
rm(i)
about_data(symptoms) # 28,228 observations and 129 variables
[1] "28,228 observations and 129 variables"
Assign values for each symptom dummy variable
for (i in seq_along(symptom_list)) {
# For each variable in symptoms that shares the name of the i'th value in symptom_list
symptoms[symptom_list[i]] <- if_else(
# If the name of the variable is found anywhere in symptoms_simplified
# Set the value of that variable to 1 in that row
# Otherwise set it to 0
stringr::str_detect(
string = symptoms$symptoms_simplified,
pattern = symptom_list[i]
), 1, 0
)
}
rm(i)
about_data(symptoms) # 28,228 observations and 129 variables
[1] "28,228 observations and 129 variables"
top
Frequency Tables
Incident complaints
In descending order of occurrence
Incident symptoms
In descending order of occurrence
Cross Tabulation of Incident Complaint by Symptoms
This table is so large that it is difficult to digest. Let’s make a heat map
top
Heat maps
Reorient the table above so that each row is a combination of incident complaint and symptom
complaint_symptoms_cross_gathered <- complaint_symptoms_cross %>%
# Gather symptom columns for heatmap
group_by(incident_complaint) %>%
gather(key = symptom, value = n, -incident_complaint) %>%
# Make the symptoms shorter/easier to read by removing everything
# including and after "_r53_1, _k59_00, etc."
mutate(symptom_short = stringr::str_replace_all(
string = symptom,
pattern = "_[a-z]\\d+\\S*",
replacement = ''
)) %>%
# Improve readability
arrange(incident_complaint, desc(n)) %>%
select(incident_complaint, symptom_short, n) %>%
print()
Some incident complaints, no symptoms are ever recorded. They are:
[1] "Animal Bite"
[2] "Auto vs. Pedestrian"
[3] "Cardiac Arrest - Possible DOA"
[4] "Drowning/Diving/SCUBA Accident"
[5] "Eye Problem/Injury"
[6] "Industrial Accident/Inaccessible Incident/Other Entrapments (Non-Vehicle)"
[7] "Invalid Assist/Lifting Assist"
[8] "Medical Alarm"
[9] "Nausea/Vomiting"
[10] "Pain"
[11] "Unresponsive"
We will drop these incident complaints from the data becasue they will add no information to the heatmaps below.
complaint_symptoms_cross_gathered <- complaint_symptoms_cross_gathered %>%
mutate(cum_n = max(cumsum(n))) %>%
filter(cum_n > 0)
Absolute occurrence
Here we are plotting the number of times that given compliant/symptom pair occurred in the data.
complaint_symptoms_heatmap <- complaint_symptoms_cross_gathered %>%
ggplot() +
geom_tile(aes(incident_complaint, symptom_short, fill = n)) +
theme(
axis.text.y = element_text(size = 9),
axis.text.x = element_text(size = 10, hjust = 1, vjust = 0.5, angle = 90)
)
Hard to read in this limited space.
* Save as image file.
* Add image to the html page
ggsave(
filename = "fig_complain_symptom_heatmap.png",
plot = complaint_symptoms_heatmap,
device = "png",
path = "../images",
width = 15,
height = 20,
units = "in"
)
Relative observation of symptoms
For each incident complaint, what was the proportion of times a given symptom was recorded when any symptoms were recorded?
relative_symptoms_heatmap <- complaint_symptoms_cross_gathered %>%
# Calculate propotions
mutate(
prop = n / max(cumsum(n))
) %>%
# Plot heatmap
ggplot() +
geom_tile(aes(incident_complaint, symptom_short, fill = prop)) +
theme(
axis.text.y = element_text(size = 9),
axis.text.x = element_text(size = 10, hjust = 1, vjust = 0.5, angle = 90)
)
Hard to read in this limited space.
* Save as image file.
* Add image to the html page
ggsave(
filename = "fig_relative_symptoms_heatmap.png",
plot = relative_symptoms_heatmap,
device = "png",
path = "../images",
width = 15,
height = 20,
units = "in"
)
top
LS0tCnRpdGxlOiAiQ3JlYXRpbmcgUGF0aWVudCBTeW1wdG9tIFRhYmxlIgpkYXRlOiAiQ3JlYXRlZDogMjAxOS0wMS0zMSA8YnI+IFVwZGF0ZWQ6IGByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY3NzOiBjdXN0b20tY3NzLmNzcwotLS0KCiMgT3ZlcnZpZXcKCkRldGFpbHMgb24gdGhlIGNvbnN0cnVjdGlvbiBvZiB0aGUgTWVkU3RhciBFUENSIFBhdGllbnQgc3ltcHRvbSB0YWJsZS4gICAxMjYgdW5pcXVlIHN5bXB0b21zIHdlcmUgcmVjb3JkZWQgZm9yIDI4NTMgY2FsbHMuICBBIHRvdGFsIG9mIDQwODYgc3ltcHRvbXMgd2VyZSByZWNvcmRlZCBhbW9uZyB0aGUgY2FsbHMuCgoKIyBMb2FkIHBhY2thZ2VzIGFuZCBkYXRhCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbW1lbnQgPSBOQSkKU3lzLnNldGVudihUWiA9ICJVUy9DZW50cmFsIikKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShiZnVuY3MpCmBgYAoKYGBge3IgZXZhbD1GQUxTRX0Kc3ltcHRvbXMgPC0gZmVhdGhlcjo6cmVhZF9mZWF0aGVyKCIvVXNlcnMvamFyZWR3aWVnYW5kL0Rlc2t0b3AvREVURUNUIFJlcG9zaXRvcnkvc3ltcHRvbXMuZmVhdGhlciIpCmBgYAoKKiBBZGRpbmcgZmlsZSBwYXRoIGZvciBERVRFQ1QgZGF0YSBzZXJ2ZXIuICAgIAoqIEJyYWQgZW1haWxlZCBDaHJpcyBIYXJ2ZXkgb24gMjAxOS0wMi0xMSB0byBtYWtlIEphcmVkIGFuIGF1dGhvcml6ZWQgdXNlci4KCmBgYHtyfQpzeW1wdG9tcyA8LSBmZWF0aGVyOjpyZWFkX2ZlYXRoZXIoIi9Wb2x1bWVzL0RFVEVDVC9vbmVfeWVhcl9kYXRhL3N5bXB0b21zLmZlYXRoZXIiKQpgYGAKCmBgYHtyfQphYm91dF9kYXRhKHN5bXB0b21zKSAjIDI4LDIyOCBvYnNlcnZhdGlvbnMgYW5kIDIgdmFyaWFibGVzCmBgYAoKW3RvcF0oI3RvcCkKCgoKCgoKCgoKCiMgU2ltcGxpZnkgc3ltcHRvbSBsaXN0CgpDdXJyZW50bHksIHRoZSBzeW1wdG9tIGxpc3QgaW5jbHVkZXMgdXBwZXIgYW5kIGxvd2VyIGNhc2UgbGV0dGVycywgc3BhY2VzLCBhbmQgc3BlY2lhbCBjaGFyYWN0ZXJzLiBUaGVzZSBhcmUgbm90IGNoYXJhY3RlcmlzdGljcyB3ZSB3YW50IG9uIG91ciB2YXJpYWJsZSBuYW1lcywgYW5kIHRoZXkgbWFrZSBtYXRjaGluZyB3aXRoIHJlZ3VsYXIgZXhwcmVzc2lvbnMgbW9yZSBkaWZmaWN1bHQuIFdlIHdhbnQgdG8gZG8gYm90aCBvZiB0aG9zZSB0aGluZ3MgYmVsb3cuIFNvLCBoZXJlIHdlIHdpbGw6CgoqIENvbnZlcnQgYWxsIGxldHRlcnMgdG8gbG93ZXIgY2FzZSAgIAoqIFJlcGxhY2Ugc3BhY2VzIHdpdGggdW5kZXJzY29yZXMgICAKKiBSZXBsYWNlIHBhcmVudGhlc2VzIHdpdGggdW5kZXJzY29yZXMgICAKKiBSZXBsYWNlIHBlcmlvZHMgd2l0aCB1bmRlcnNjb3JlcyAgCiogUmVwbGFjZSBjb21tYXMgd2l0aCB1bmRlcnNjb3JlcyAgCiogUmVwbGFjZSBhbGwgaW5zdGFuY2VzIG9mIDIgb3IgbW9yZSBjb25zZWN1dGl2ZSB1bmRlcnNjb3JlcyB3ZSBjcmVhdGVkIGluIHRoZSBwcm9jZXNzIHdpdGggc2luZ2xlIHVuZGVyc2NvcmVzICAgCiogUmVtb3ZlIHRyYWlsaW5nIHVuZGVyc2NvcmVzICAgCgpgYGB7cn0Kc2ltcGxpZnlfc3ltcHRvbV9zdHJpbmdzIDwtIGZ1bmN0aW9uKHgpIHsKICB4ICU+JSAKICAgIHRvbG93ZXIoKSAlPiUgCiAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwocGF0dGVybiA9ICJcXHMiLCByZXBsYWNlbWVudCA9ICJfIikgJT4lICMgd2hpdGUgc3BhY2UKICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChwYXR0ZXJuID0gIltcXCh8XFwpXSIsIHJlcGxhY2VtZW50ID0gIl8iKSAlPiUgIyBwYXJlbnRoZXNlcwogICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHBhdHRlcm4gPSAiXFwuIiwgcmVwbGFjZW1lbnQgPSAiXyIpICU+JSAjIHBlcmlvZHMKICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChwYXR0ZXJuID0gIlxcLCg/PVxcXykiLCByZXBsYWNlbWVudCA9ICJfIikgJT4lICMgY29tbWFzIC0gbm90IHNlcGFyYXRpbmcgc3ltcHRvbXMKICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChwYXR0ZXJuID0gIlxcX3syLH0iLCByZXBsYWNlbWVudCA9ICJfIikgJT4lICMgbXVsdGlwbGUgdW5kZXJzY29yZXMKICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChwYXR0ZXJuID0gIlxcXyg/PVxcJykiLCByZXBsYWNlbWVudCA9ICIiKSAjIHRyYWlsaW5nIHVuZGVyc2NvcmVzCn0KYGBgCgpgYGB7cn0Kc3ltcHRvbXMgPC0gc3ltcHRvbXMgJT4lIAogIG11dGF0ZShzeW1wdG9tc19zaW1wbGlmaWVkID0gc2ltcGxpZnlfc3ltcHRvbV9zdHJpbmdzKHN5bXB0b21zKSkKYGBgCgpgYGB7cn0KYWJvdXRfZGF0YShzeW1wdG9tcykgIyAyOCwyMjggb2JzZXJ2YXRpb25zIGFuZCAzIHZhcmlhYmxlcwpgYGAKClt0b3BdKCN0b3ApCgoKCgoKCgoKCgojIEZpbmQgYWxsIHN5bXB0b21zCgoqIEZpZ3VyZSBvdXQgaG93IHRvIGJyZWFrIGNoYXJhY3RlciBzdGluZ3MgaW50byBjb21wb25lbnQgc3ltcHRvbXMgICAKKiBHZXQgbGlzdCBvZiBhbGwgdW5pcXVlIHN5bXB0b21zICAgCiogVHVybiBzeW1wdG9tcyBpbnRvIGJpbmFyeSB2YXJpYWJsZXMgICAKKiBDcmVhdGUgbmV3IHRhYmxlIG9mIHN5bXB0b21zICAgCiogQ3JlYXRlIHR3by13YXkgdGFibGUgb2Ygc3ltcHRvbXMgYnkgaW5jaWRlbnQgY29tcGxhaW50ICAgCgoKIyMgQ3JlYXRlIExpc3Qgb2YgVW5pcXVlIFN5bXB0b21zCgpgYGB7cn0Kc3ltcHRvbV9saXN0IDwtIHN5bXB0b21zICU+JSAKICBmaWx0ZXIoIWlzLm5hKHN5bXB0b21zX3NpbXBsaWZpZWQpKSAlPiUgIyBSZW1vdmUgTkEKICBwdWxsKHN5bXB0b21zX3NpbXBsaWZpZWQpICU+JSAjIENvZXJjZSB0byB2ZWN0b3IgCiAgdW5pcXVlKCkgJT4lICMgR2V0cyB1bmlxdWUgZ3JvdXBzIG9mIHN5bXB0b21zCiAgc3RyaW5ncjo6c3RyX3NwbGl0KHBhdHRlcm4gPSAiJycsJyciKSAlPiUgIyBTcGxpdHMgY2hhcmFjdGVyIHN0cmluZyBhdCAnJywnJwogIHVubGlzdCgpICU+JSAjIENvZXJjZSBmcm9tIGxpc3QgdG8gdmVjdG9yCiAgc3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwoIiciKSAlPiUgIyBSZW1vdmUgcmVtYWluaW5nIHNpbmdsZSBxdW90ZXMKICB1bmlxdWUoKSAjIEdldCB1bmlxdWUgc3ltcHRvbXMKYGBgCgoKIyMgQ3JlYXRlIGR1bW15IHZhcmlhYmxlcyBmb3IgZWFjaCBzeW1wdG9tLCBieSB0aGUgc2FtZSBuYW1lCgpgYGB7cn0KZm9yIChpIGluIHNlcV9hbG9uZyhzeW1wdG9tX2xpc3QpKSB7CiAgc3ltcHRvbXNbc3ltcHRvbV9saXN0W2ldXSA8LSBOQQp9CnJtKGkpCmBgYAoKYGBge3J9CmFib3V0X2RhdGEoc3ltcHRvbXMpICMgMjgsMjI4IG9ic2VydmF0aW9ucyBhbmQgMTI5IHZhcmlhYmxlcwpgYGAKCgojIyBBc3NpZ24gdmFsdWVzIGZvciBlYWNoIHN5bXB0b20gZHVtbXkgdmFyaWFibGUKCmBgYHtyfQpmb3IgKGkgaW4gc2VxX2Fsb25nKHN5bXB0b21fbGlzdCkpIHsKICAjIEZvciBlYWNoIHZhcmlhYmxlIGluIHN5bXB0b21zIHRoYXQgc2hhcmVzIHRoZSBuYW1lIG9mIHRoZSBpJ3RoIHZhbHVlIGluIHN5bXB0b21fbGlzdAogIHN5bXB0b21zW3N5bXB0b21fbGlzdFtpXV0gPC0gaWZfZWxzZSggCiAgICAjIElmIHRoZSBuYW1lIG9mIHRoZSB2YXJpYWJsZSBpcyBmb3VuZCBhbnl3aGVyZSBpbiBzeW1wdG9tc19zaW1wbGlmaWVkCiAgICAjIFNldCB0aGUgdmFsdWUgb2YgdGhhdCB2YXJpYWJsZSB0byAxIGluIHRoYXQgcm93CiAgICAjIE90aGVyd2lzZSBzZXQgaXQgdG8gMAogICAgc3RyaW5ncjo6c3RyX2RldGVjdCgKICAgICAgc3RyaW5nID0gc3ltcHRvbXMkc3ltcHRvbXNfc2ltcGxpZmllZCwgCiAgICAgIHBhdHRlcm4gPSBzeW1wdG9tX2xpc3RbaV0KICAgICksIDEsIDAKICApCn0Kcm0oaSkKYGBgCgpgYGB7cn0KYWJvdXRfZGF0YShzeW1wdG9tcykgIyAyOCwyMjggb2JzZXJ2YXRpb25zIGFuZCAxMjkgdmFyaWFibGVzCmBgYAoKW3RvcF0oI3RvcCkKCgoKCgoKCgoKCiMgRnJlcXVlbmN5IFRhYmxlcwoKCiMjIEluY2lkZW50IGNvbXBsYWludHMKCkluIGRlc2NlbmRpbmcgb3JkZXIgb2Ygb2NjdXJyZW5jZQoKYGBge3IgZWNobz1GQUxTRX0Kc3ltcHRvbXMgJT4lIAogIGdyb3VwX2J5KGluY2lkZW50X2NvbXBsYWludCkgJT4lIAogIHN1bW1hcmlzZShuID0gbigpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBhcnJhbmdlKGRlc2MobikpICU+JSAKICBtdXRhdGUocGVyY2VudCA9IG4gLyBtYXgoY3Vtc3VtKG4pKSAqIDEwMCkKYGBgCgoKIyMgSW5jaWRlbnQgc3ltcHRvbXMKCkluIGRlc2NlbmRpbmcgb3JkZXIgb2Ygb2NjdXJyZW5jZQoKYGBge3IgZWNobz1GQUxTRX0Kc3ltcHRvbXMgJT4lIAogIHNlbGVjdCgtaW5jaWRlbnRfY29tcGxhaW50LCAtc3ltcHRvbXMsIC1zeW1wdG9tc19zaW1wbGlmaWVkKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChmdW5zKHN1bSguLCBuYS5ybSA9IFRSVUUpKSkgJT4lIAogIHRpZHlyOjpnYXRoZXIoa2V5ID0gInN5bXB0b20iLCB2YWx1ZSA9ICJuIikgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSkgJT4lIAogIG11dGF0ZShwZXJjZW50ID0gbiAvIG1heChjdW1zdW0obikpICogMTAwKQpgYGAKCgojIyBDcm9zcyBUYWJ1bGF0aW9uIG9mIEluY2lkZW50IENvbXBsYWludCBieSBTeW1wdG9tcwoKYGBge3IgZWNobz1GQUxTRX0KY29tcGxhaW50X3N5bXB0b21zX2Nyb3NzIDwtIHN5bXB0b21zICU+JSAKICBzZWxlY3QoLXN5bXB0b21zLCAtc3ltcHRvbXNfc2ltcGxpZmllZCkgJT4lIAogIGdyb3VwX2J5KGluY2lkZW50X2NvbXBsYWludCkgJT4lIAogIHN1bW1hcmlzZV9pZigKICAgIC5wcmVkaWNhdGUgPSBpcy5udW1lcmljLAogICAgLmZ1bnMgPSBmdW5zKHN1bSguLCBuYS5ybSA9IFRSVUUpKQogICkgJT4lIAogIHByaW50KCkKYGBgCgpUaGlzIHRhYmxlIGlzIHNvIGxhcmdlIHRoYXQgaXQgaXMgZGlmZmljdWx0IHRvIGRpZ2VzdC4gTGV0J3MgbWFrZSBhIGhlYXQgbWFwCgpbdG9wXSgjdG9wKQoKCgoKCgoKCgoKIyBIZWF0IG1hcHMKClJlb3JpZW50IHRoZSB0YWJsZSBhYm92ZSBzbyB0aGF0IGVhY2ggcm93IGlzIGEgY29tYmluYXRpb24gb2YgaW5jaWRlbnQgY29tcGxhaW50IGFuZCBzeW1wdG9tCgpgYGB7cn0KY29tcGxhaW50X3N5bXB0b21zX2Nyb3NzX2dhdGhlcmVkIDwtIGNvbXBsYWludF9zeW1wdG9tc19jcm9zcyAlPiUgCiAgCiAgIyBHYXRoZXIgc3ltcHRvbSBjb2x1bW5zIGZvciBoZWF0bWFwCiAgZ3JvdXBfYnkoaW5jaWRlbnRfY29tcGxhaW50KSAlPiUgCiAgZ2F0aGVyKGtleSA9IHN5bXB0b20sIHZhbHVlID0gbiwgLWluY2lkZW50X2NvbXBsYWludCkgJT4lIAogIAogICMgTWFrZSB0aGUgc3ltcHRvbXMgc2hvcnRlci9lYXNpZXIgdG8gcmVhZCBieSByZW1vdmluZyBldmVyeXRoaW5nCiAgIyBpbmNsdWRpbmcgYW5kIGFmdGVyICJfcjUzXzEsIF9rNTlfMDAsIGV0Yy4iCiAgbXV0YXRlKHN5bXB0b21fc2hvcnQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiAgICBzdHJpbmcgPSBzeW1wdG9tLAogICAgcGF0dGVybiA9ICJfW2Etel1cXGQrXFxTKiIsCiAgICByZXBsYWNlbWVudCA9ICcnCiAgKSkgJT4lIAogIAogICMgSW1wcm92ZSByZWFkYWJpbGl0eQogIGFycmFuZ2UoaW5jaWRlbnRfY29tcGxhaW50LCBkZXNjKG4pKSAlPiUgCiAgc2VsZWN0KGluY2lkZW50X2NvbXBsYWludCwgc3ltcHRvbV9zaG9ydCwgbikgJT4lICAKICBwcmludCgpCmBgYAoKU29tZSBpbmNpZGVudCBjb21wbGFpbnRzLCBubyBzeW1wdG9tcyBhcmUgZXZlciByZWNvcmRlZC4gVGhleSBhcmU6CgpgYGB7ciBlY2hvPUZBTFNFfQpjb21wbGFpbnRfc3ltcHRvbXNfY3Jvc3NfZ2F0aGVyZWQgJT4lIAogIG11dGF0ZShjdW1fbiA9IG1heChjdW1zdW0obikpKSAlPiUgCiAgZmlsdGVyKGN1bV9uID09IDApICU+JSAKICBwdWxsKGluY2lkZW50X2NvbXBsYWludCkgJT4lIAogIHVuaXF1ZSgpCmBgYAoKV2Ugd2lsbCBkcm9wIHRoZXNlIGluY2lkZW50IGNvbXBsYWludHMgZnJvbSB0aGUgZGF0YSBiZWNhc3VlIHRoZXkgd2lsbCBhZGQgbm8gaW5mb3JtYXRpb24gdG8gdGhlIGhlYXRtYXBzIGJlbG93LgoKYGBge3J9CmNvbXBsYWludF9zeW1wdG9tc19jcm9zc19nYXRoZXJlZCA8LSBjb21wbGFpbnRfc3ltcHRvbXNfY3Jvc3NfZ2F0aGVyZWQgJT4lIAogIG11dGF0ZShjdW1fbiA9IG1heChjdW1zdW0obikpKSAlPiUgCiAgZmlsdGVyKGN1bV9uID4gMCkKYGBgCgoKIyMgQWJzb2x1dGUgb2NjdXJyZW5jZQoKSGVyZSB3ZSBhcmUgcGxvdHRpbmcgdGhlIG51bWJlciBvZiB0aW1lcyB0aGF0IGdpdmVuIGNvbXBsaWFudC9zeW1wdG9tIHBhaXIgb2NjdXJyZWQgaW4gdGhlIGRhdGEuCgpgYGB7cn0KY29tcGxhaW50X3N5bXB0b21zX2hlYXRtYXAgPC0gY29tcGxhaW50X3N5bXB0b21zX2Nyb3NzX2dhdGhlcmVkICU+JSAKICBnZ3Bsb3QoKSArCiAgICBnZW9tX3RpbGUoYWVzKGluY2lkZW50X2NvbXBsYWludCwgc3ltcHRvbV9zaG9ydCwgZmlsbCA9IG4pKSArIAogICAgdGhlbWUoCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41LCBhbmdsZSA9IDkwKQogICAgKQpgYGAKCkhhcmQgdG8gcmVhZCBpbiB0aGlzIGxpbWl0ZWQgc3BhY2UuICAgIAoqIFNhdmUgYXMgaW1hZ2UgZmlsZS4gICAKKiBBZGQgaW1hZ2UgdG8gdGhlIGh0bWwgcGFnZSAgIAoKYGBge3J9Cmdnc2F2ZSgKICBmaWxlbmFtZSA9ICJmaWdfY29tcGxhaW5fc3ltcHRvbV9oZWF0bWFwLnBuZyIsCiAgcGxvdCA9IGNvbXBsYWludF9zeW1wdG9tc19oZWF0bWFwLAogIGRldmljZSA9ICJwbmciLAogIHBhdGggPSAiLi4vaW1hZ2VzIiwKICB3aWR0aCA9IDE1LAogIGhlaWdodCA9IDIwLAogIHVuaXRzID0gImluIgopCmBgYAoKIVtdKC4uL2ltYWdlcy9maWdfY29tcGxhaW5fc3ltcHRvbV9oZWF0bWFwLnBuZykKCgojIyBSZWxhdGl2ZSBvYnNlcnZhdGlvbiBvZiBzeW1wdG9tcwoKRm9yIGVhY2ggaW5jaWRlbnQgY29tcGxhaW50LCB3aGF0IHdhcyB0aGUgcHJvcG9ydGlvbiBvZiB0aW1lcyBhIGdpdmVuIHN5bXB0b20gd2FzIHJlY29yZGVkIHdoZW4gYW55IHN5bXB0b21zIHdlcmUgcmVjb3JkZWQ/CgpgYGB7cn0KcmVsYXRpdmVfc3ltcHRvbXNfaGVhdG1hcCA8LSBjb21wbGFpbnRfc3ltcHRvbXNfY3Jvc3NfZ2F0aGVyZWQgJT4lIAoKICAjIENhbGN1bGF0ZSBwcm9wb3Rpb25zCiAgbXV0YXRlKAogICAgcHJvcCA9IG4gLyBtYXgoY3Vtc3VtKG4pKQogICkgJT4lIAogIAogICMgUGxvdCBoZWF0bWFwCiAgZ2dwbG90KCkgKwogICAgZ2VvbV90aWxlKGFlcyhpbmNpZGVudF9jb21wbGFpbnQsIHN5bXB0b21fc2hvcnQsIGZpbGwgPSBwcm9wKSkgKwogICAgdGhlbWUoCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41LCBhbmdsZSA9IDkwKQogICAgKQpgYGAKCkhhcmQgdG8gcmVhZCBpbiB0aGlzIGxpbWl0ZWQgc3BhY2UuICAgIAoqIFNhdmUgYXMgaW1hZ2UgZmlsZS4gICAKKiBBZGQgaW1hZ2UgdG8gdGhlIGh0bWwgcGFnZSAgIAoKYGBge3J9Cmdnc2F2ZSgKICBmaWxlbmFtZSA9ICJmaWdfcmVsYXRpdmVfc3ltcHRvbXNfaGVhdG1hcC5wbmciLAogIHBsb3QgPSByZWxhdGl2ZV9zeW1wdG9tc19oZWF0bWFwLAogIGRldmljZSA9ICJwbmciLAogIHBhdGggPSAiLi4vaW1hZ2VzIiwKICB3aWR0aCA9IDE1LAogIGhlaWdodCA9IDIwLAogIHVuaXRzID0gImluIgopCmBgYAoKIVtdKC4uL2ltYWdlcy9maWdfcmVsYXRpdmVfc3ltcHRvbXNfaGVhdG1hcC5wbmcpCgpbdG9wXSgjdG9wKQoKCgoKCgoKCgoKIyBTZXNzaW9uIGluZm9ybWF0aW9uCgpgYGB7ciBlY2hvPUZBTFNFfQpybShsaXN0ID0gbHMoKSkKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpzZXNzaW9uSW5mbygpCmBgYAoKPHNjcmlwdCBzcmM9InNjcmlwdC5qcyI+PC9zY3JpcHQ+